# -*- coding: utf-8 -*-
"""
数据模型定义

功能说明:
- 定义应用的数据模型
- 搜索历史模型
- 用户信息模型
- 内容生成模型
- 缓存数据模型

作者: MetasoCreator Team
创建时间: 2025-08-19
"""

from datetime import datetime, timezone
from typing import Dict, Any, List, Optional
from dataclasses import dataclass, field
from enum import Enum
import json


class SearchStatus(Enum):
    """搜索状态枚举"""
    PENDING = "pending"      # 待处理
    PROCESSING = "processing"  # 处理中
    COMPLETED = "completed"   # 已完成
    FAILED = "failed"        # 失败
    CACHED = "cached"        # 缓存结果


class ContentType(Enum):
    """内容类型枚举"""
    WEB_SEARCH = "web_search"    # 网页搜索
    CONTENT_READ = "content_read"  # 内容阅读
    QA_ANSWER = "qa_answer"      # 问答回答
    SUMMARY = "summary"          # 内容摘要
    ANALYSIS = "analysis"        # 内容分析


@dataclass
class SearchResult:
    """搜索结果数据模型"""
    title: str                    # 标题
    url: str                     # 链接
    snippet: str                 # 摘要
    content: str = ""            # 完整内容
    score: float = 0.0           # 相关性评分
    source: str = ""             # 来源
    publish_time: Optional[str] = None  # 发布时间
    author: str = ""             # 作者
    tags: List[str] = field(default_factory=list)  # 标签
    metadata: Dict[str, Any] = field(default_factory=dict)  # 元数据
    
    def to_dict(self) -> Dict[str, Any]:
        """转换为字典格式"""
        return {
            'title': self.title,
            'url': self.url,
            'snippet': self.snippet,
            'content': self.content,
            'score': self.score,
            'source': self.source,
            'publish_time': self.publish_time,
            'author': self.author,
            'tags': self.tags,
            'metadata': self.metadata
        }
    
    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> 'SearchResult':
        """从字典创建实例"""
        return cls(
            title=data.get('title', ''),
            url=data.get('url', ''),
            snippet=data.get('snippet', ''),
            content=data.get('content', ''),
            score=data.get('score', 0.0),
            source=data.get('source', ''),
            publish_time=data.get('publish_time'),
            author=data.get('author', ''),
            tags=data.get('tags', []),
            metadata=data.get('metadata', {})
        )


@dataclass
class SearchQuery:
    """搜索查询数据模型"""
    query: str                   # 查询词
    user_id: Optional[str] = None  # 用户ID
    session_id: str = ""         # 会话ID
    language: str = "zh"         # 语言
    region: str = "CN"           # 地区
    limit: int = 10              # 结果数量限制
    scope: str = "web"           # 搜索范围
    filters: Dict[str, Any] = field(default_factory=dict)  # 过滤条件
    options: Dict[str, Any] = field(default_factory=dict)  # 其他选项
    timestamp: datetime = field(default_factory=lambda: datetime.now(timezone.utc))
    
    def to_dict(self) -> Dict[str, Any]:
        """转换为字典格式"""
        return {
            'query': self.query,
            'user_id': self.user_id,
            'session_id': self.session_id,
            'language': self.language,
            'region': self.region,
            'limit': self.limit,
            'scope': self.scope,
            'filters': self.filters,
            'options': self.options,
            'timestamp': self.timestamp.isoformat()
        }
    
    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> 'SearchQuery':
        """从字典创建实例"""
        timestamp = data.get('timestamp')
        if isinstance(timestamp, str):
            timestamp = datetime.fromisoformat(timestamp.replace('Z', '+00:00'))
        elif timestamp is None:
            timestamp = datetime.now(timezone.utc)
        
        return cls(
            query=data.get('query', ''),
            user_id=data.get('user_id'),
            session_id=data.get('session_id', ''),
            language=data.get('language', 'zh'),
            region=data.get('region', 'CN'),
            limit=data.get('limit', 10),
            scope=data.get('scope', 'web'),
            filters=data.get('filters', {}),
            options=data.get('options', {}),
            timestamp=timestamp
        )


@dataclass
class SearchHistory:
    """搜索历史数据模型"""
    id: str                      # 历史记录ID
    user_id: str                 # 用户ID
    query: str                   # 查询词
    result_count: int            # 结果数量
    status: SearchStatus         # 搜索状态
    content_type: ContentType    # 内容类型
    response_time: float = 0.0   # 响应时间（秒）
    error_message: str = ""      # 错误信息
    metadata: Dict[str, Any] = field(default_factory=dict)  # 元数据
    created_at: datetime = field(default_factory=lambda: datetime.now(timezone.utc))
    updated_at: datetime = field(default_factory=lambda: datetime.now(timezone.utc))
    
    def to_dict(self) -> Dict[str, Any]:
        """转换为字典格式"""
        return {
            'id': self.id,
            'user_id': self.user_id,
            'query': self.query,
            'result_count': self.result_count,
            'status': self.status.value,
            'content_type': self.content_type.value,
            'response_time': self.response_time,
            'error_message': self.error_message,
            'metadata': self.metadata,
            'created_at': self.created_at.isoformat(),
            'updated_at': self.updated_at.isoformat()
        }
    
    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> 'SearchHistory':
        """从字典创建实例"""
        created_at = data.get('created_at')
        if isinstance(created_at, str):
            created_at = datetime.fromisoformat(created_at.replace('Z', '+00:00'))
        elif created_at is None:
            created_at = datetime.now(timezone.utc)
        
        updated_at = data.get('updated_at')
        if isinstance(updated_at, str):
            updated_at = datetime.fromisoformat(updated_at.replace('Z', '+00:00'))
        elif updated_at is None:
            updated_at = datetime.now(timezone.utc)
        
        return cls(
            id=data.get('id', ''),
            user_id=data.get('user_id', ''),
            query=data.get('query', ''),
            result_count=data.get('result_count', 0),
            status=SearchStatus(data.get('status', 'pending')),
            content_type=ContentType(data.get('content_type', 'web_search')),
            response_time=data.get('response_time', 0.0),
            error_message=data.get('error_message', ''),
            metadata=data.get('metadata', {}),
            created_at=created_at,
            updated_at=updated_at
        )


@dataclass
class UserProfile:
    """用户档案数据模型"""
    user_id: str                 # 用户ID
    username: str = ""           # 用户名
    email: str = ""              # 邮箱
    preferences: Dict[str, Any] = field(default_factory=dict)  # 用户偏好
    search_count: int = 0        # 搜索次数
    last_search_time: Optional[datetime] = None  # 最后搜索时间
    created_at: datetime = field(default_factory=lambda: datetime.now(timezone.utc))
    updated_at: datetime = field(default_factory=lambda: datetime.now(timezone.utc))
    is_active: bool = True       # 是否活跃
    
    def to_dict(self) -> Dict[str, Any]:
        """转换为字典格式"""
        return {
            'user_id': self.user_id,
            'username': self.username,
            'email': self.email,
            'preferences': self.preferences,
            'search_count': self.search_count,
            'last_search_time': self.last_search_time.isoformat() if self.last_search_time else None,
            'created_at': self.created_at.isoformat(),
            'updated_at': self.updated_at.isoformat(),
            'is_active': self.is_active
        }
    
    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> 'UserProfile':
        """从字典创建实例"""
        last_search_time = data.get('last_search_time')
        if isinstance(last_search_time, str):
            last_search_time = datetime.fromisoformat(last_search_time.replace('Z', '+00:00'))
        
        created_at = data.get('created_at')
        if isinstance(created_at, str):
            created_at = datetime.fromisoformat(created_at.replace('Z', '+00:00'))
        elif created_at is None:
            created_at = datetime.now(timezone.utc)
        
        updated_at = data.get('updated_at')
        if isinstance(updated_at, str):
            updated_at = datetime.fromisoformat(updated_at.replace('Z', '+00:00'))
        elif updated_at is None:
            updated_at = datetime.now(timezone.utc)
        
        return cls(
            user_id=data.get('user_id', ''),
            username=data.get('username', ''),
            email=data.get('email', ''),
            preferences=data.get('preferences', {}),
            search_count=data.get('search_count', 0),
            last_search_time=last_search_time,
            created_at=created_at,
            updated_at=updated_at,
            is_active=data.get('is_active', True)
        )


@dataclass
class CacheEntry:
    """缓存条目数据模型"""
    key: str                     # 缓存键
    value: Any                   # 缓存值
    ttl: int = 3600             # 生存时间（秒）
    created_at: datetime = field(default_factory=lambda: datetime.now(timezone.utc))
    accessed_at: datetime = field(default_factory=lambda: datetime.now(timezone.utc))
    access_count: int = 0        # 访问次数
    
    def is_expired(self) -> bool:
        """检查是否过期"""
        if self.ttl <= 0:
            return False  # 永不过期
        
        elapsed = (datetime.now(timezone.utc) - self.created_at).total_seconds()
        return elapsed > self.ttl
    
    def to_dict(self) -> Dict[str, Any]:
        """转换为字典格式"""
        return {
            'key': self.key,
            'value': self.value,
            'ttl': self.ttl,
            'created_at': self.created_at.isoformat(),
            'accessed_at': self.accessed_at.isoformat(),
            'access_count': self.access_count
        }
    
    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> 'CacheEntry':
        """从字典创建实例"""
        created_at = data.get('created_at')
        if isinstance(created_at, str):
            created_at = datetime.fromisoformat(created_at.replace('Z', '+00:00'))
        elif created_at is None:
            created_at = datetime.now(timezone.utc)
        
        accessed_at = data.get('accessed_at')
        if isinstance(accessed_at, str):
            accessed_at = datetime.fromisoformat(accessed_at.replace('Z', '+00:00'))
        elif accessed_at is None:
            accessed_at = datetime.now(timezone.utc)
        
        return cls(
            key=data.get('key', ''),
            value=data.get('value'),
            ttl=data.get('ttl', 3600),
            created_at=created_at,
            accessed_at=accessed_at,
            access_count=data.get('access_count', 0)
        )


@dataclass
class APIResponse:
    """API响应数据模型"""
    success: bool                # 是否成功
    data: Optional[Any] = None   # 响应数据
    message: str = ""            # 响应消息
    error_code: str = ""         # 错误代码
    timestamp: datetime = field(default_factory=lambda: datetime.now(timezone.utc))
    request_id: str = ""         # 请求ID
    
    def to_dict(self) -> Dict[str, Any]:
        """转换为字典格式"""
        result = {
            'success': self.success,
            'timestamp': self.timestamp.isoformat(),
            'message': self.message
        }
        
        if self.data is not None:
            result['data'] = self.data
        
        if self.error_code:
            result['error_code'] = self.error_code
        
        if self.request_id:
            result['request_id'] = self.request_id
        
        return result
    
    @classmethod
    def success_response(cls, data: Any = None, message: str = "操作成功") -> 'APIResponse':
        """创建成功响应"""
        return cls(success=True, data=data, message=message)
    
    @classmethod
    def error_response(cls, message: str = "操作失败", error_code: str = "") -> 'APIResponse':
        """创建错误响应"""
        return cls(success=False, message=message, error_code=error_code)


class ModelEncoder(json.JSONEncoder):
    """自定义JSON编码器，用于序列化数据模型"""
    
    def default(self, obj):
        if hasattr(obj, 'to_dict'):
            return obj.to_dict()
        elif isinstance(obj, datetime):
            return obj.isoformat()
        elif isinstance(obj, Enum):
            return obj.value
        return super().default(obj)


def serialize_model(model) -> str:
    """序列化数据模型为JSON字符串"""
    return json.dumps(model, cls=ModelEncoder, ensure_ascii=False)


def deserialize_search_result(data: str) -> Optional[SearchResult]:
    """反序列化搜索结果"""
    try:
        parsed_data = json.loads(data)
        return SearchResult.from_dict(parsed_data)
    except Exception:
        return None


def deserialize_search_history(data: str) -> Optional[SearchHistory]:
    """反序列化搜索历史"""
    try:
        parsed_data = json.loads(data)
        return SearchHistory.from_dict(parsed_data)
    except Exception:
        return None


def deserialize_user_profile(data: str) -> Optional[UserProfile]:
    """反序列化用户档案"""
    try:
        parsed_data = json.loads(data)
        return UserProfile.from_dict(parsed_data)
    except Exception:
        return None